/*!
 * 文件名称： driver_fmc.c
 * 描    述： fmc 驱动文件
 * 版本：     2023-12-03, V1.0
*/

/*
* GD32F303东方红开发板V1.0
* 淘宝商城：   https://juwo.taobao.com
* 技术交流：   https://www.gd32bbs.com/ask/
* 视频学习：   https://space.bilibili.com/475462605
* 微信公众号： gd32bbs
* Copyright    苏州聚沃电子科技有限公司
* 版权所有，盗版必究。
*/

#include "driver_fmc.h"

/*!
* 说明       向内部Flash写入数据
* 输入[1]    write_start_addr：写入数据的Flash地址  
* 输入[2]    data_buf：        写入数据的buf指针
* 输入[3]    data_lengh：      写入数据的长度
* 返回值     无
*/
void fmc_write_data_16b(uint32_t write_start_addr, uint16_t *data_buf, uint16_t data_lengh)
{
        uint32_t write_addr,erase_addr;
        uint16_t data_write_num=0;
        int16_t data_earse_num;
        fmc_unlock();                                                    /* 解锁FMC */
        /* 清除BANK0和BANK1的错误标志 */
        fmc_flag_clear(FMC_FLAG_BANK0_PGERR|FMC_FLAG_BANK0_WPERR|FMC_FLAG_BANK0_END);
        fmc_flag_clear(FMC_FLAG_BANK1_PGERR|FMC_FLAG_BANK1_WPERR|FMC_FLAG_BANK1_END);
        
        
        erase_addr = write_start_addr;
        data_earse_num = data_lengh;
        /* 若写入起始地址加上总长*2小于0x08080000，说明需要擦写的数据均在BANK0，页大小为2K/页 */
        if((write_start_addr+data_lengh*2)<0x08080000)
        {
            /* 若写入地址为页起始地址 */
            if(write_start_addr%2048 == 0)
            {
                for(;data_earse_num>0;)
                {
                    fmc_page_erase(erase_addr);
                    erase_addr+=2048;
                    data_earse_num-=1024;
                }
                /*若写入地址不是页起始地址*/
            }else{
                    for(;(data_earse_num>0||erase_addr>=write_start_addr+data_lengh*2);)
                    {
                        fmc_page_erase(erase_addr);
                        erase_addr+=2048;
                        data_earse_num-=1024;
                    }
                }
            /* 若写入地址加上写入长度*2大于0x08080000，说明擦写的数据可能跨BANK或者均在BANK1，页大小有差别 */
        }else{
            /* 如果起始地址小于0x08080000，说明跨BANK */
            if(write_start_addr<0x08080000)
            {
                /* 首先擦除BANK0部分所需页 */
                for(;erase_addr<0x08080000;)
                {
                        fmc_page_erase(erase_addr);
                        erase_addr+=2048;
                }
                /* 然后擦除BANK1部分所需页 */
                erase_addr = 0x08080000;
                for(;erase_addr<=write_start_addr+data_lengh*2;)
                {
                        fmc_page_erase(erase_addr);
                        erase_addr+=4096;
                }
            }else{
                /*若写入地址大于等于0x08080000,说明均在BANK1，页大小为4K/页*/
            if(write_start_addr%4096 == 0)  /* 若写入地址为页起始地址 */
            {
                for(;data_earse_num>0;)
                {
                    fmc_page_erase(erase_addr);
                    erase_addr+=4096;
                    data_earse_num-=2048;
                }
            }else{
                    /*若写入地址不是页起始地址*/
                    for(;(data_earse_num>0||erase_addr>=write_start_addr+data_lengh*2);)
                    {
                        fmc_page_erase(erase_addr);
                        erase_addr+=4096;
                        data_earse_num-=2048;
                    }
                }
            }
        }
        
        /* 写入数据 */
        write_addr = write_start_addr;
        for(data_write_num = 0; data_write_num<data_lengh;data_write_num++)
        {
            fmc_halfword_program(write_addr, data_buf[data_write_num]);
            write_addr += 2;
        }
        fmc_lock();
}

/*!
* 说明       读取Flash地址数据
* 输入[1]    write_read_addr：需要读取的Flash地址
* 返回值     读取的数据
*/
uint16_t fmc_read_data_16b(uint32_t write_read_addr)
{
        return *(uint16_t *)write_read_addr;
}

